/**
 ****************************************************************
 * @file iso15693.h
 *
 * @brief
 *
 * @author
 *
 *
 ****************************************************************
 */

#ifndef ISO15693_H
#define ISO15693_H

#include <stdint.h>
#include "nfc_hal_config.h"
#include "nfc_hal_transfer.h"

/* 0x00: Anti-collision based on slot;  0x01: Anti-collision based on bit and time slot
   Note: If there are many labels, the recommended value is 0x00 */
#define USE_BIT_AND_SLOT_ANTI_COLLSION                      0x00

#define	ISO15693_UID_LENGTH									0x08

#define ERROR_FLAG											BIT(0)	//RSP FLAG

#define SUB_CARRIER_FLAG									BIT(0)
#define DATA_RATE_FLAG										BIT(1)
#define INVENTORY_FLAG										BIT(2)
#define PROTOCOL_EXTENSION_FLAG								BIT(3)

#define SELECT_FLAG											BIT(4)	//INVENTORY_FLAG = 0
#define ADDRESS_FLAG										BIT(5)
#define OPTION_FLAG											BIT(6)

#define AFI_FLAG											BIT(4)	//INVENTORY_FLAG = 1
#define NB_SLOTS_FLAG										BIT(5)
#define OPTION_FLAG											BIT(6)

#define	INVENTORY_CMD										0x01
#define	STAY_QUIET_CMD										0x02
#define READ_SINGLE_BLOCK_CMD 								0x20
#define	WRITE_SINGLE_BLOCK_CMD								0x21
#define LOCK_BLOCK_CMD										0x22
#define	READ_MULTIPLE_BLOCK_CMD								0x23
#define	WRITE_MULTIPLE_BLOCK_CMD 							0x24
#define	SELECT_CMD											0x25
#define	RESET_TO_READY_CMD									0x26
#define	WRITE_AFI_CMD										0x27
#define	LOCK_AFI_CMD										0x28
#define	WRITE_DSFID_CMD										0x29
#define	LOCK_DSFID_CMD										0x2A
#define	GET_SYSTEM_INFORMATION_CMD							0x2B
#define	GET_MULTTIPLE_BLOCK_SECURITY_STATUS_CMD	     		0x2C


#define ISO15693_INVENTORY_RSP_LEN							10U
#define ISO15693_STAY_QUIET_CMD_RSP_LEN						10U

#define	mask_bit_number(x)		 BIT((x - 1) % 8)
#define	mask_byte_number(z)		 ((z - 1) / 8)
#define	bit_random(a)			 (a % 2)

//Indicates the number of labels used by iso15693 for time slot conflict prevention
#define TYPEV_PICC_NUMBER       							0x05

typedef struct
{
    uint8_t bCardNum;
    uint8_t bCollPend;
    struct  /*phacDiscLoop_TypeV*/
    {
        uint8_t bDsfid;      /**< [Out] Data Storage Format Identifier. */
        uint8_t aUid[8];     /**< [Out] UID Received from card */
    } aTypeV[TYPEV_PICC_NUMBER];     //TYPEV_PICC_NUMBER indicates the number of cards
} TypeV_Info_t;

int pcd_send_eof(uint8_t *pRxBuffer, uint16_t *pRxLength);

int pcd_inventory(
    uint8_t  bFlag,
    uint8_t  bAfi,
    uint8_t *pMask,
    uint8_t  bMaskBitLength,
    TypeV_Info_t *pTypeV_Info_t
);

int pcd_stay_quiet(uint8_t *pUid, uint8_t bFlag);

int pcd_reset_to_ready(uint8_t *pUid, uint8_t bFlag);

int pcd_read_single_block(
    uint8_t  *pUid,
    uint8_t   bFlag,
    uint8_t   bBlockNum,
    uint8_t  *pRxBuffer,
    uint8_t  *pErr,
    uint16_t *pRxLength
);

int pcd_write_single_block(
    uint8_t  *pUid,
    uint8_t	bFlag,
    uint8_t	bBlockNum,
    uint8_t  *pTxBuffer,
    uint8_t  *pErr,
    uint16_t	wTxLength
);

int com_write_read_blocks_and_check(
   uint8_t  *pUid,     
   uint8_t   bFlag,
   uint8_t   bBlockNum,
   uint8_t   bNumBlocks,
   uint8_t  *pErr,
   uint8_t  *pRxBuffer,
   uint8_t  *pTxBuffer,
   uint16_t *pRxLength,
   uint16_t *pTxLength
);

int pcd_lock_block(uint8_t *pUid, uint8_t bFlag, uint8_t bBlockNum, uint8_t *pErr);

int pcd_read_multiple_block(
    uint8_t  *pUid,
    uint8_t  bFlag,
    uint8_t  bBlockNum,
    uint8_t  bNumBlocks,
    uint8_t  *pRxBuffer,
    uint8_t  *pErr,
    uint16_t *pRxLength
);

int pcd_write_multiple_block(
    uint8_t  *pUid,
    uint8_t   bFlag,
    uint8_t   bBlockNum,
    uint8_t   bNumBlocks,
    uint8_t  *pTxBuffer,
    uint8_t  *pErr,
    uint16_t  wTxLength
);

int pcd_select(uint8_t *pUid, uint8_t bFlag, uint8_t *pErr);

int pcd_write_afi(uint8_t *pUid, uint8_t bFlag, uint8_t bAfi, uint8_t *pErr);

int pcd_lock_afi(uint8_t *pUid, uint8_t bFlag, uint8_t *pErr);

int pcd_write_dsfid(uint8_t *pUid, uint8_t bFlag, uint8_t bDsfid, uint8_t *pErr);

int pcd_lock_dsfid(uint8_t *pUid, uint8_t bFlag, uint8_t *pErr);

int pcd_get_system_information(
    uint8_t  *pUid,
    uint8_t   bFlag,
    uint8_t  *pErr,
    uint8_t  *pRxBuffer,
    uint16_t *pRxLength
);

int pcd_get_multiple_block_security_status(
    uint8_t  *pUid,
    uint8_t   bFlag,
    uint8_t   bBlockNum,
    uint8_t   bNumBlocks,
    uint8_t  *pErr,
    uint8_t  *pSecurityStatus,
    uint16_t *pSecStaLength
);

void pcd_set_15693_tmo(uint8_t time);

#endif
